package cn.kent.high.questions.futureTask;

import java.util.concurrent.*;

/**
 * 问题产生：
 * 线程池使用{@link java.util.concurrent.FutureTask}时，如果把拒绝策略设置成了ThreadPoolExecutor.DiscardPolicy 或 DiscardOldestPolicy
 * 并且在被拒绝的任务Future对象上调用了无参get方法，那么调用线程会一直阻塞。
 *
 * 以下代码复现问题：
 *
 * 解决方案：
 * 带有延时时间的get方法
 */
public class FutureTest {
    private static final ThreadPoolExecutor executorService = new ThreadPoolExecutor(1, 1,
            1L, TimeUnit.MINUTES,
            new ArrayBlockingQueue<Runnable>(1), new ThreadPoolExecutor.DiscardOldestPolicy());
    // AbortPolicy | DiscardPolicy | DiscardOldestPolicy
    // DiscardOldestPolicy | DiscardPolicy -> 阻塞到2
    // AbortPolicy 正常运行，丢弃

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 添加任务one
        Future fOne = executorService.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("start task one");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        // 添加任务two
        Future fTwo = executorService.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("start task two");
            }
        });

        // 添加任务three
        Future fThree = null;
        try {
            fThree = executorService.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("start task three");
                }
            });
        } catch (Exception e) {
            System.out.println(e.getLocalizedMessage());
        }

        System.out.println("thread one " + fOne.get()); // 等待任务one执行结束
        System.out.println("thread two " + fTwo.get()); // 等待任务two执行结束
        System.out.println("thread three " + (fThree == null ? null : fThree.get()));
        System.out.println("开始关闭");

        executorService.shutdown(); // 关闭线程池，阻塞直到所有任务执行结束
    }
}
